home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / field_index.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-04  |  30.7 KB  |  990 lines

  1. /* 
  2.  * field_index.c -- 
  3.  * ITIID           : $ITI$ $Header $__Header$
  4.  * Author          : Huynh Quoc T. Tung
  5.  * Created On      : Fri Mar  4 11:15:41 1994
  6.  * Last Modified By: Ulrich Pfeifer
  7.  * Last Modified On: Wed Sep  7 15:14:22 1994
  8.  * Update Count    : 114
  9.  * Status          : Unknown, Use with caution!
  10.  */
  11.  
  12. #include "cdialect.h"
  13. #include "futil.h"
  14. #include "field_index.h"
  15. #include "irhash.h"             /* STOP_WORD_FLAG */
  16. #define MAX_FIELDS_NAMES 30
  17. #define MAX_WORD_LENGTH 20
  18. #define MAX_LINE_LENGTH 1000
  19.  
  20. #ifdef STEM_WORDS
  21. boolean index_stemming = false; /* used in irtfiles.c */
  22. #endif
  23.  
  24. static boolean not_field = false;   /* not_field = true,
  25.                                 if line is not to add in a field */
  26. static boolean is_field = false;    /* is_field = true, 
  27.                                 if line is to add in a field */
  28. static boolean local_not_indexed = false; /* line not indexed */
  29.  
  30. fields_struct** index_fields = NULL;
  31.  
  32. nidx_table* Ntable = NULL;     /* for lines which are not indexed 
  33.                                   defined in field_y.c */
  34. ltable* Ltable = NULL; /* for layout */
  35.  
  36. #ifdef SYSVREGEXP
  37. /* --------------------- sgrep function --------------------------- */
  38.  
  39. #include "../regexp/regexp.h"
  40.  
  41. static int number_of_expbuf = 0;
  42. regexp **expbuf_set;
  43.  
  44. /* ------------------------------------------------------------- */
  45. /* compile regexp only one,
  46.    regexp's compiled are in expbuf_set.
  47.    return 0 if success,
  48.    return -1 if error. */
  49.  
  50.  
  51.  
  52. long compile_regexp (number_of_regexp, regexp_set)
  53.      long number_of_regexp;
  54.      char** regexp_set;
  55. {
  56.   long i;
  57.  
  58.   number_of_expbuf = number_of_regexp;
  59.  
  60.   if(number_of_regexp == 0)
  61.     return(0);
  62.   expbuf_set = (regexp **)
  63.     malloc(number_of_regexp*sizeof(regexp *));
  64.   for(i=0; i< number_of_regexp; i++) {
  65.     expbuf_set[i] = regcomp(regexp_set[i]);
  66.     if (expbuf_set[i] == NULL) {
  67.       return(-1);
  68.     }
  69.   }
  70.   return(0);
  71. }
  72. /* ------------------------------------------------------------- */
  73.  
  74. static char* sgrep _AP((char* s, regexp* expbuf,  long* begin_pos, long* end_pos));
  75.  
  76. static char* sgrep(s, expbuf, begin_pos, end_pos)
  77.      char* s;
  78.      regexp* expbuf;
  79.      long* begin_pos;
  80.      long* end_pos;
  81. {
  82.   if (regexec(expbuf, s)) { /* match */
  83.     if(begin_pos != NULL)
  84.       *begin_pos = expbuf->startp[0] - s;
  85.     if(end_pos != NULL)
  86.       *end_pos = expbuf->endp[0] - s;
  87.     return(expbuf->startp[0]);
  88.   }
  89.   return(NULL);
  90. }
  91. /* ------------------------------------------------------------- */
  92. /* matching line with regexp.
  93.    regexp_pos is the position of compiled regexp.
  94.  */
  95. char* match(line, begin_pos, end_pos, regexp_pos)
  96.      char* line;
  97.      long* begin_pos;
  98.      long* end_pos;
  99.      long regexp_pos;
  100. {
  101.   return(sgrep(line, expbuf_set[regexp_pos], 
  102.                begin_pos, end_pos));
  103. }
  104. #else
  105. /* --------------------- sgrep function --------------------------- */
  106.  
  107. #define INIT register char *regexp=instring;
  108. #define GETC() (*regexp++)
  109. #define PEEKC() (*regexp)
  110. #define UNGETC(c) (regexp--)
  111. #define RETURN(pointer) return(0);          /* return 0 on sucess */
  112. #define ERROR(val) return((char *) val);    /* return error code on failure */
  113. #ifndef SYSVREGEXP
  114. #ifndef HAVE_GETRNGE
  115. static getrnge _AP((char *string));
  116. #endif /* HAVE_GETRNGE */
  117. #endif /* SYSVREGEXP */
  118. #include <regexp.h>
  119.  
  120. char** expbuf_set = NULL;
  121.  
  122. /* ------------------------------------------------------------- */
  123. /* compile regexp only one,
  124.    regexp's compiled are in expbuf_set.
  125.    return 0 if success,
  126.    return -1 if error. */
  127.  
  128. static int* circf_set = NULL;
  129. static int number_of_expbuf = 0;
  130.  
  131. long compile_regexp(number_of_regexp, regexp_set)
  132.      long number_of_regexp;
  133.      char** regexp_set;
  134. {
  135.   long i;
  136.   int  status;
  137.   char eof;
  138.   char *c;
  139.   char *endbuf;
  140.  
  141.   number_of_expbuf = number_of_regexp;
  142.  
  143.   if(number_of_regexp == 0)
  144.     return(0);
  145.   
  146.   if(circf_set == NULL)
  147.     circf_set = (int*)s_malloc((size_t)(sizeof(int) * number_of_regexp));
  148.   expbuf_set = 
  149.     (char**)s_malloc((size_t)(sizeof(char*) * number_of_regexp));
  150.   for(i=0; i< number_of_regexp; i++) {
  151.     expbuf_set[i] = (char*)s_malloc((size_t)(sizeof(char) * 1024));
  152.     endbuf = (expbuf_set[i])+1024; /* end of buffer */
  153.     status = (int) compile(regexp_set[i], expbuf_set[i], endbuf, eof='\0');
  154.     circf_set[i] = circf;
  155.     if(status)
  156.       return(-1);
  157.   }
  158.   return(0);
  159. }
  160. /* ------------------------------------------------------------- */
  161.  
  162. static char* sgrep _AP((char* s, char* expbuf, int lcircf, long* begin_pos, long* end_pos));
  163. static char* sgrep(s, expbuf, lcircf, begin_pos, end_pos)
  164.      char* s;
  165.      char* expbuf;
  166.      int lcircf;
  167.      long* begin_pos;
  168.      long* end_pos;
  169. {
  170.   char *c;
  171.  
  172.   circf = lcircf;
  173.   if (step(s, expbuf)) { /* match */
  174.     if(begin_pos != NULL)
  175.       *begin_pos = loc1 - s;
  176.     if(end_pos != NULL)
  177.       *end_pos = loc2 - s;
  178.     return(loc1);
  179.   }
  180.   return(NULL);
  181. }
  182. /* ------------------------------------------------------------- */
  183. /* matching line with regexp.
  184.    regexp_pos is the position of compiled regexp.
  185.  */
  186. char* match(line, begin_pos, end_pos, regexp_pos)
  187.      char* line;
  188.      long* begin_pos;
  189.      long* end_pos;
  190.      long regexp_pos;
  191. {
  192.   return(sgrep(line, expbuf_set[regexp_pos], circf_set[regexp_pos],
  193.                begin_pos, end_pos));
  194. }
  195. #endif
  196. /* ------------------------------------------------------------- */
  197.  
  198. static void clear_expbuf _AP((void));
  199. static void clear_expbuf()
  200. {
  201.   long i;
  202.   for(i=0; i< number_of_expbuf; i++) 
  203.     s_free(/* (char *) */(expbuf_set[i]));
  204.   s_free(expbuf_set);
  205. }
  206.  
  207. /* ------------------------------------------------------------- */
  208. static void clear_ntable _AP((void));
  209. static void clear_ntable()
  210. {
  211.   long i;
  212.   
  213.   if(Ntable != NULL) {
  214.     s_free(Ntable->begin_tag_pos);
  215.     s_free(Ntable->end_tag_pos);
  216.     s_free(Ntable);
  217.   }
  218. }
  219. /* ------------------------------------------------------------- */
  220.  
  221. static void clear_fields_Ftable _AP((database* db));
  222. static void clear_fields_Ftable(db)
  223.      database* db;
  224. {
  225.   long i, j, k;
  226.  
  227.   if(index_fields != NULL) {
  228.     for(i=0; i<db->number_of_fields; i++) {
  229.       j = index_fields[i]->number_of_Ftable;
  230.       while(j > 0) {
  231.         s_free(index_fields[i]->Ftable[j-1].index_kind);
  232.         for(k=0; k < NUMBER_OF_INDEXTYPES; k++) {
  233.           if(index_fields[i]->Ftable[j-1].indextypes[k] == NULL)
  234.             break;
  235.           else s_free(index_fields[i]->Ftable[j-1].indextypes[k]);
  236.         }
  237.         s_free(index_fields[i]->Ftable[j-1].indextypes);
  238.         --j;
  239.       }
  240.       s_free(index_fields[i]->Ftable);
  241.       if (index_fields[i]->field_name) s_free(index_fields[i]->field_name);
  242.       s_free(index_fields[i]);
  243.     }
  244.     s_free(index_fields);
  245.   }
  246.   db->index_fields = NULL;
  247.   return;                       /* return(0) (up) */
  248. }
  249. /* ------------------------------------------------------------- */
  250.  
  251. static void clear_Ltable _AP((void));
  252. static void clear_Ltable()
  253. {
  254.   long i;
  255.   
  256.   if(Ltable != NULL) {
  257.     s_free(Ltable->layout);
  258.     if(Ltable->date_desc != NULL)
  259.       s_free(Ltable->date_desc);
  260.     if(Ltable->sscanf_arg != NULL)
  261.       s_free(Ltable->sscanf_arg);
  262.     s_free(Ltable);
  263.   }
  264.   return;                    /* return(0); (up) */
  265. }
  266.  
  267. /* ------------------------------------------------------------- */
  268.  
  269. void clear_fields(db)
  270.      database* db;
  271. {
  272.   clear_fields_Ftable(db);
  273.   clear_Ftable_pos();
  274.   clear_ntable();
  275.   clear_Ltable();
  276.   clear_expbuf();
  277.   return;                    /* return(0); (up) */
  278. }
  279.  
  280. /* ------------------------------------------------------------- */
  281. static index_fields_struct* index_fields_array;
  282. long Maxfield_names = 0;
  283. long Nfield_names = 0;
  284.  
  285. static void clear_index_fields_array _AP((long number_of_elements));
  286. static void clear_index_fields_array(number_of_elements)
  287.      long number_of_elements;
  288. {
  289.   long i;
  290.   
  291.   if(index_fields_array != NULL) {
  292.     for(i=0; i<number_of_elements; i++) {
  293.       s_free(index_fields_array->field_names[i]);
  294.     }
  295.     s_free(index_fields_array->numeric);
  296.     /* should'nt we free this too ?(up) */
  297.     s_free(index_fields_array->field_names); 
  298.     s_free(index_fields_array);
  299.   }
  300.   Maxfield_names = 0;
  301.   Nfield_names = 0;
  302. }
  303. /* ------------------------------------------------------------- */
  304.  
  305.   
  306. /* store the name and field_id of fields to generate */
  307.  
  308. long save_index_fields(field_name, number_of_elements, field_id)
  309.      char* field_name;
  310.      long* number_of_elements;
  311.      long *field_id;
  312. {
  313.   long i = 0;
  314.   long len;
  315.   
  316.   if(index_fields_array != NULL) {
  317.     for(i=0; i<*number_of_elements; i++) {
  318.       if(field_name == NULL) {
  319.         if(index_fields_array->field_names[i] == NULL) {
  320.           *field_id = i;
  321.           return(0);
  322.         }
  323.       }
  324.       else {
  325.         if(index_fields_array->field_names[i] != NULL) 
  326.           if(!strcmp(field_name, index_fields_array->field_names[i])) {
  327.             *field_id = i;
  328.             return(0);
  329.           }
  330.       }
  331.     }
  332.     if(Nfield_names >= Maxfield_names) {
  333.       Maxfield_names += MAX_FIELDS_NAMES;
  334.       index_fields_array->field_names = 
  335.         (char**)s_realloc(index_fields_array->field_names, 
  336.                           (size_t)(sizeof(char*) * Maxfield_names));
  337.       index_fields_array->numeric =
  338.         (boolean*)s_realloc(index_fields_array->numeric,
  339.                             (size_t)(sizeof(boolean) * Maxfield_names));
  340.     }
  341.     ++Nfield_names;
  342.     *field_id = i;
  343.     *number_of_elements += 1;
  344.     index_fields_array->numeric[i] = false;
  345.     if(field_name != NULL) {
  346.       len = strlen(field_name);
  347.       index_fields_array->field_names[i] = 
  348.         (char*)s_malloc((size_t)(sizeof(char) * (len + 2)));
  349.       s_strncpy(index_fields_array->field_names[i], field_name, len + 1);
  350.     }
  351.     else index_fields_array->field_names[i] = NULL;
  352.   }
  353.   else {
  354.     index_fields_array = (index_fields_struct*)
  355.       s_malloc((size_t)(sizeof(index_fields_struct)));
  356.     Maxfield_names = Nfield_names + MAX_FIELDS_NAMES;
  357.     index_fields_array->field_names = /* nobody frees this? (up) */
  358.       (char**)s_malloc((size_t)(sizeof(char*) * Maxfield_names));
  359.     index_fields_array->numeric =
  360.       (boolean*)s_malloc((size_t)(sizeof(boolean) * Maxfield_names));
  361.     if(field_name != NULL) {
  362.       len = strlen(field_name);
  363.       index_fields_array->field_names[i] = 
  364.         (char*)s_malloc((size_t)(sizeof(char) * (len + 2)));
  365.       s_strncpy(index_fields_array->field_names[i],field_name, len + 1);
  366.     }
  367.     else index_fields_array->field_names[i] = NULL;
  368.     index_fields_array->numeric[i] = false;
  369.     ++Nfield_names;
  370.     *field_id = 0;
  371.     *number_of_elements += 1;
  372.   }
  373.   return(1);
  374. }
  375. /* ------------------------------------------------------------- */
  376.  
  377. void save_numeric_index_fields(field_id)
  378.      long field_id;
  379. {
  380.   index_fields_array->numeric[field_id] = true;
  381. }
  382. /* ------------------------------------------------------------- */
  383.  
  384. static long* Ftable_pos = NULL;
  385.  
  386. void clear_Ftable_pos()
  387. {
  388.   if(Ftable_pos != NULL)
  389.     s_free(Ftable_pos);
  390. }
  391.  
  392.  
  393. /* ------------------------------------------------------------- */
  394. /* checking how a line should be indexed.
  395.  */
  396.  
  397. long how_index_line(field_id, line, 
  398.                     number_of_not_ended_section,
  399.                     document_id,
  400.                     weight,
  401.                     file_position_before_line,
  402.                     line_length,
  403.                     newline_terminated,
  404.                     db,
  405.                     wordfunction1,
  406.                     wordfunction2,
  407.                     word_position, word_pairs,
  408.                     minwordlen, type)    
  409.      long field_id;
  410.      char* line;
  411.      long* number_of_not_ended_section;
  412.      long document_id;
  413.      long weight;
  414.      long file_position_before_line;
  415.      long *line_length;
  416.      boolean *newline_terminated;
  417.      database* db;
  418.      wordfunc* wordfunction1;
  419.      wordfunc* wordfunction2;
  420.      boolean word_position, word_pairs;
  421.      int minwordlen;
  422.      char* type;
  423. {
  424.   long i, fpos, tmplen;
  425.   long char_count;
  426.   long lnumber_of_not_ended_section;
  427.   long begin_pos; /* This is  a  pointer  to the 
  428.            * first character that matched 
  429.            * the regular expression.
  430.            */
  431.   long end_pos;   /* This is  a  pointer  to the
  432.            * to the character after  the  
  433.            * last  character that matches 
  434.            * the regular expression.
  435.            */
  436.   long index_pos, n_index_pos;
  437.   long rest;
  438.   char* matchline = NULL;
  439.   char tmpline[MAX_LINE_LENGTH];
  440.   char indexline[MAX_LINE_LENGTH];
  441.  
  442.   s_strncpy(tmpline, line, MAX_LINE_LENGTH);
  443.   tmplen = strlen(tmpline);
  444.  /* if(tmpline[tmplen - 1] == '\n')
  445.     tmpline[tmplen - 1] = '\0'; */
  446.   s_strncpy(indexline, line, MAX_LINE_LENGTH);
  447.  
  448.   /* if the end_marke of previous line not found then
  449.      continues to search for the end_marke.
  450.    */
  451.   if(*number_of_not_ended_section > 0) {
  452.     lnumber_of_not_ended_section = *number_of_not_ended_section;
  453.     for(i=0; i<*number_of_not_ended_section; i++) {
  454.       if(Ftable_pos[i] > -1) { 
  455.         fpos = Ftable_pos[i];
  456.         if(match(tmpline,&end_pos,NULL,
  457.                  db->index_fields[field_id]->Ftable[fpos].end_tag_pos)) {
  458.           if(end_pos > 0) /* copy n-character until end_pos */
  459.             s_strncpy(indexline, tmpline, end_pos + 1);
  460.           else indexline[0] = '\0'; /* if the end_marke at begin of line then not index this line */
  461.           Ftable_pos[i] = -1;
  462.           --lnumber_of_not_ended_section;
  463.         }
  464.         /* end_marke not yet found */
  465.         else s_strncpy(indexline, tmpline, MAX_LINE_LENGTH);
  466.       }
  467.       else --lnumber_of_not_ended_section;
  468.       if(indexline[0] != '\0') {
  469.         if(-1 == index_line_section(field_id, fpos,
  470.                                     indexline,
  471.                                     document_id,
  472.                                     weight,
  473.                                     file_position_before_line,
  474.                                     line_length,
  475.                                     newline_terminated,
  476.                                     db,
  477.                                     wordfunction1,
  478.                                     wordfunction2,
  479.                                     word_position, word_pairs,
  480.                                     minwordlen, type))
  481.           waislog(WLOG_HIGH, WLOG_ERROR, "map_over_words failed");
  482.       }
  483.     }
  484.     if(lnumber_of_not_ended_section == 0) 
  485.       *number_of_not_ended_section = 0;
  486.   }
  487.   
  488.   for(i=0; i < db->index_fields[field_id]->number_of_Ftable; i++) { /* check for field_name */
  489.     if((matchline = s_strdup(match(tmpline, &begin_pos, &end_pos, 
  490.                                    db->index_fields[field_id]->Ftable[i].begin_tag_pos)))) { 
  491.       /* match field */
  492.       for(char_count=0; char_count<begin_pos; char_count++) 
  493.         indexline[char_count] = ' ';
  494.       s_strncpy(&indexline[begin_pos], matchline, MAX_LINE_LENGTH - begin_pos);
  495.  
  496.       /* the index position is giving. 
  497.          The line should be indexed exactly at index_pos.
  498.        */
  499.       if(db->index_fields[field_id]->Ftable[i].index_pos > -1) {
  500.         if(matchline != NULL) s_free(matchline);
  501.         if(match(tmpline, NULL, &index_pos,
  502.                  db->index_fields[field_id]->Ftable[i].index_pos)) {
  503.           for(char_count=0; char_count<index_pos - 1; char_count++) 
  504.             indexline[char_count] = ' ';
  505.           if(match(&tmpline[index_pos-1], &end_pos, NULL, db->index_fields[field_id]->Ftable[i].end_tag_pos)) 
  506.             s_strncpy(&indexline[index_pos-1], &tmpline[index_pos-1],end_pos + 1);
  507.           else {
  508.             s_strncpy(&indexline[index_pos-1], &tmpline[index_pos-1], MAX_LINE_LENGTH - index_pos - 1);
  509.             if(Ftable_pos == NULL)
  510.               Ftable_pos = (long*)s_malloc((size_t)sizeof(long) * 10);
  511.             else {
  512.               if(*number_of_not_ended_section >= 10) {
  513.                 Ftable_pos = (long*) s_realloc(Ftable_pos, 
  514.                                                (size_t)sizeof(long) * (*number_of_not_ended_section + 10));
  515.               }
  516.             }
  517.             Ftable_pos[*number_of_not_ended_section] = i;
  518.             ++(*number_of_not_ended_section);
  519.           }
  520.         }
  521.       }
  522.       else {
  523.         for(char_count=0; char_count<begin_pos; char_count++) 
  524.           indexline[char_count] = ' ';
  525.     rest = end_pos - begin_pos;
  526.         if(match(&tmpline[end_pos], &end_pos, NULL, db->index_fields[field_id]->Ftable[i].end_tag_pos))
  527.           s_strncpy(&indexline[begin_pos], matchline, end_pos + rest + 1);
  528.         else {
  529.           if(Ftable_pos == NULL)
  530.             Ftable_pos = (long*)s_malloc((size_t)sizeof(long) * 10);
  531.           else {
  532.             if(*number_of_not_ended_section >= 10) {
  533.               Ftable_pos = (long*) s_realloc(Ftable_pos, 
  534.                                              (size_t)sizeof(long) * (*number_of_not_ended_section + 10));
  535.             }
  536.           }
  537.           Ftable_pos[*number_of_not_ended_section] = i;
  538.           ++(*number_of_not_ended_section);
  539.         }
  540.       }
  541.  
  542.       /* It is a numeric field. */
  543.  
  544.       if(db->index_fields[field_id]->numeric) {
  545.         
  546.         if(db->index_fields[field_id]->n_index_pos > -1) {
  547.  
  548.           /* Indexing line at n_index_pos, 
  549.              or at index_pos or at beginning of line 
  550.            */
  551.           if(match(tmpline, NULL, &n_index_pos,
  552.                    db->index_fields[field_id]->n_index_pos)) {
  553.             for(char_count=0; char_count<n_index_pos - 1; char_count++) 
  554.               indexline[char_count] = ' ';
  555.         if(db->index_fields[field_id]->numeric_len > 0) {
  556.           s_strncpy(&indexline[n_index_pos-1], &tmpline[n_index_pos-1], 
  557.             db->index_fields[field_id]->numeric_len + 1);
  558.         } else {
  559.           if(end_pos > 0) {
  560.         s_strncpy(&indexline[n_index_pos-1], &tmpline[n_index_pos-1],end_pos + 1);
  561.           } else {
  562.         s_strncpy(&indexline[n_index_pos-1], &tmpline[n_index_pos-1],
  563.               MAX_LINE_LENGTH - n_index_pos);
  564.           }
  565.         }
  566.           }
  567.         }
  568.     else {
  569.       if(db->index_fields[field_id]->numeric_len > 0) {
  570.         indexline[db->index_fields[field_id]->numeric_len] = '\0';
  571.       }
  572.     }
  573.       }
  574.       
  575.       if(-1 == index_line_section(field_id, i,
  576.                                   indexline,
  577.                                   document_id,
  578.                                   weight,
  579.                                   file_position_before_line,
  580.                                   line_length,
  581.                                   newline_terminated,
  582.                                   db,
  583.                                   wordfunction1,
  584.                                   wordfunction2,
  585.                                   word_position, word_pairs,
  586.                                   minwordlen, type))
  587.         waislog(WLOG_HIGH, WLOG_ERROR, "map_over_words failed");
  588.     
  589.       if(matchline != NULL) s_free(matchline);
  590.     }
  591.   }
  592.   if(matchline != NULL) s_free(matchline);
  593.   return(0);
  594. }
  595. /* ------------------------------------------------------------- */
  596.  
  597. /* line: it is a line that is not to index.
  598.    line_length: number of character of line.
  599.    newline_terminated = true if the line terminates with a newline,
  600.    else newline_terminated = false.
  601. */
  602.  
  603. long count_words(line, line_length, newline_terminated)
  604.      char* line;
  605.      long* line_length;
  606.      boolean* newline_terminated;
  607. {
  608.   unsigned long ch;
  609.   long char_count = 0;
  610.   long word_len = 0;
  611.   long word_count = 0;
  612.   
  613.   for(ch = (unsigned char)line[char_count++]; 
  614.       ch != '\0'; ch = (unsigned char)line[char_count++]){
  615.    
  616.     boolean alnum = isalnum(ch);
  617.     
  618.     if(alnum) 
  619.       word_len++;
  620.     else {
  621.       if(word_len != 0)
  622.         if(word_len >= 2)
  623.           word_count++;
  624.       word_len = 0;
  625.     }
  626.   }
  627.   if(newline_terminated != NULL){
  628.     if('\n' != line[char_count-2])
  629.       *newline_terminated = false;
  630.     else
  631.       *newline_terminated = true;
  632.   }
  633.   if(line_length != NULL)
  634.     *line_length = char_count - 1;
  635.   return(word_count);
  636. }
  637. /* ------------------------------------------------------------- */
  638.  
  639. /* The line should be indexed as in the field_description file */
  640.  
  641. long index_line_section(field_id, fpos,
  642.                         line,
  643.                         document_id,
  644.                         weight,
  645.                         file_position_before_line,
  646.                         line_length,
  647.                         newline_terminated,
  648.                            db,
  649.                         wordfunction1,
  650.                         wordfunction2,
  651.                         word_position, word_pairs,
  652.                         minwordlen, type)    
  653.      long field_id;
  654.      long fpos;
  655.      char* line;
  656.      long document_id;
  657.      long weight;
  658.      long file_position_before_line;
  659.      long *line_length;
  660.      boolean *newline_terminated;
  661.      database* db;
  662.      wordfunc* wordfunction1;
  663.      wordfunc* wordfunction2;
  664.      boolean word_position, word_pairs;
  665.      int minwordlen;
  666.      char* type;
  667. {
  668.   long i = 0;
  669.   long number_of_words = 0;
  670.   
  671.   char** indextypes = db->index_fields[field_id]->Ftable[fpos].indextypes;
  672.   int*  index_kind = db->index_fields[field_id]->Ftable[fpos].index_kind;
  673.  
  674.   while(indextypes[i]) {
  675.     if(!strncmp(indextypes[i],TEXT,strlen(TEXT)))
  676.       type = NULL;
  677.     else {
  678.       type = indextypes[i];
  679.     }
  680.     if(index_kind[i] == I_GLOBAL) {
  681.       not_field = true;
  682.       is_field = false;
  683.     }
  684.     else {
  685.       not_field = false;
  686.       is_field = true;
  687.     }
  688.       
  689.     if(not_field) {
  690. #ifdef STEM_WORDS
  691.       if(db->stemming)
  692.     index_stemming = true;
  693.       else index_stemming = false;
  694. #endif
  695.       number_of_words = map_over_words(line, document_id, 
  696.                                        weight, 
  697.                                        file_position_before_line,
  698.                                        line_length, 
  699.                                        newline_terminated,
  700.                                        db,    
  701.                                        wordfunction1,
  702.                                        word_position, word_pairs,
  703. #ifdef SOUND
  704.                                        minwordlen, type);
  705. #else
  706.                                        minwordlen);
  707. #endif
  708. #ifdef STEM_WORDS
  709.     index_stemming = false;
  710. #endif
  711.     }
  712.     else { /* is_field */
  713. #ifdef STEM_WORDS
  714.       if(db->fields[field_id].stemming)
  715.     index_stemming = true;      /* used in map_over_words of irtfiles.c */
  716.       else index_stemming = false;
  717. #endif
  718.       number_of_words = map_over_words(line, document_id, 
  719.                                        weight, 
  720.                                        file_position_before_line,
  721.                                        line_length, 
  722.                                        newline_terminated,
  723.                                        db,    
  724.                                        wordfunction2,
  725.                                        word_position, word_pairs,
  726. #ifdef SOUND
  727.                                        minwordlen, type);
  728. #else
  729.                                        minwordlen);
  730. #endif
  731. #ifdef STEM_WORDS
  732.     index_stemming = false;
  733. #endif
  734.     }
  735.     ++i;
  736.   }
  737.   if(is_field)
  738.     db->fields[field_id].total_word_count += number_of_words;
  739.   return(number_of_words);
  740. }
  741. /* ------------------------------------------------------------- */
  742.  
  743. static char *rmprefix = NULL;
  744.  
  745. static int rmselector(file)
  746. struct dirent *file;
  747. {
  748.   /* printf("selector: %s\n", file->d_name); */
  749.   return(!strncmp(file->d_name,rmprefix,strlen(rmprefix)));
  750. }
  751.  
  752. static int prefremove(dir, prefix)
  753. char *dir, *prefix;
  754. {
  755.   struct dirent **matches;
  756.   char path[MAX_FILENAME_LEN];
  757.   int i;
  758.  
  759.   rmprefix = prefix;
  760.   strcpy(path,dir);
  761.   strncat(path,"/",MAX_FILENAME_LEN);
  762.   
  763.   if ( scandir(dir, &matches, rmselector, NULL) > 0 ) {
  764.       for(i=0;matches[i];i++) {
  765.         path[strlen(dir)+1] = '\0';
  766.         strncat(path,matches[i]->d_name,MAX_FILENAME_LEN);
  767.         s_free(matches[i]);
  768.         waislog(WLOG_LOW, WLOG_INFO, "deleting \"%s\"", path);
  769.         if (unlink(path)) {
  770.             waislog(WLOG_HIGH, WLOG_ERROR, "unlink failed");
  771.         }
  772.       }
  773.       s_free(matches);
  774.   }
  775.   return(i);
  776. }
  777.     
  778.     
  779. /* insert all fields to create */
  780. boolean init_index_fields(adding_to_existing_index, create_new_fields, 
  781.                           field_adding_to_existing_index, number_of_fields, db)
  782.      boolean* adding_to_existing_index;
  783.      boolean* create_new_fields;
  784.      boolean field_adding_to_existing_index;
  785.      long number_of_fields;
  786.      database* db;
  787. {
  788.   long i, j;
  789.   long fno_len, fna_len, em_len, idx_len, nidx_flen, nidx_elen;
  790.   long number_of_fields_not_exists = 0;
  791.   char file[1001];
  792.   /* char* system_call; */
  793.   char* field_name;
  794.   
  795.   if(number_of_fields == 0)
  796.     return(0);
  797.  
  798.   db->fields = 
  799.     (field_db*)s_malloc((size_t)(sizeof(field_db) * number_of_fields));
  800.   if(db->field_index_streams == NULL)
  801.     db->field_index_streams = (FILE**)s_malloc((size_t)sizeof(FILE*));
  802.   if(db->field_dictionary_streams == NULL)
  803.     db->field_dictionary_streams = (FILE**)s_malloc((size_t)sizeof(FILE*));
  804.  
  805.   if(*create_new_fields && !field_adding_to_existing_index) {
  806.     field_name = (char*)s_malloc((size_t)(sizeof(char) * (MAX_FILENAME_LEN + 1)));
  807.     db->number_of_fields = 0;
  808.   }
  809.   
  810.   for(i= 0; i< number_of_fields; i++) {
  811.     /* only fields which not exist will be created */
  812.     if(*create_new_fields && !field_adding_to_existing_index) {
  813.       if(index_fields_array->field_names[i] != NULL) {
  814.         s_strncpy(field_name, db->database_file, MAX_FILENAME_LEN);
  815.         s_strncat(field_name,field_ext,MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  816.         s_strncat(field_name,index_fields_array->field_names[i],
  817.                   MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  818.         s_strncat(field_name,dictionary_ext,MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  819.         if(!probe_file(field_name)) {
  820.           db->fields[number_of_fields_not_exists].field_id = i;
  821.           db->fields[number_of_fields_not_exists].index_file_number = 0;
  822.           db->fields[number_of_fields_not_exists].total_word_count = 0;
  823.           db->fields[number_of_fields_not_exists].numeric = index_fields_array->numeric[i];
  824.       db->fields[number_of_fields_not_exists].stemming = index_fields[i]->stemming;
  825.           fna_len = strlen(index_fields_array->field_names[i]);
  826.           db->fields[number_of_fields_not_exists].field_name = 
  827.             (char*)s_malloc((size_t)(sizeof(char) * (fna_len + 2)));
  828.           s_strncpy(db->fields[number_of_fields_not_exists].field_name, 
  829.                     index_fields_array->field_names[i], fna_len + 1);
  830.           ++number_of_fields_not_exists;
  831.         }
  832.       }
  833.       db->number_of_fields += number_of_fields_not_exists;
  834.     }
  835.     else { /* insert all field names in database */
  836.       db->fields[i].field_id = i;
  837.       db->fields[i].index_file_number = 0;
  838.       db->fields[i].total_word_count = 0;
  839.       if(index_fields_array->field_names[i] != NULL) {
  840.         fna_len = strlen(index_fields_array->field_names[i]);
  841.         db->fields[i].field_name = 
  842.           (char*)s_malloc((size_t)(sizeof(char) * (fna_len + 2)));
  843.         s_strncpy(db->fields[i].field_name,index_fields_array->field_names[i], 
  844.                   fna_len + 1);
  845.       }
  846.       else db->fields[i].field_name = NULL;
  847.       db->fields[i].numeric = index_fields_array->numeric[i];
  848.       db->fields[i].stemming = index_fields[i]->stemming;
  849.     }
  850.   }
  851.   clear_index_fields_array(number_of_fields);
  852.   
  853.   /* delete all fields exist */
  854.   
  855.   if(!*adding_to_existing_index) {
  856.     if(!*create_new_fields) {
  857.       char dir[MAX_FILENAME_LEN];
  858.       char *prefix;
  859.       int files_deleted;
  860.  
  861.       strcpy(dir, db->database_file);
  862.       strncat(dir, field_ext,MAX_FILENAME_LEN);
  863.       for(prefix=dir+strlen(dir);prefix>=dir && *prefix!='/';*prefix--);
  864.       if (*prefix = '/') {      /* path given */
  865.         *(prefix++) = '\0';
  866.         files_deleted = prefremove(dir, prefix);
  867.       } else {                  /* database in current dir */
  868.         files_deleted = prefremove("./", dir);
  869.       }
  870.       /*
  871.       system_call = (char*)s_malloc((size_t)(sizeof(char) * (1000 + 3)));
  872.       strncpy(system_call, "rm ", MAX_FILENAME_LEN + 3);
  873.       s_strncat(system_call, db->database_file,
  874.                 MAX_FILENAME_LEN, MAX_FILENAME_LEN);
  875.       s_strncat(system_call, field_ext, MAX_FILENAME_LEN, MAX_FILENAME_LEN);
  876.       s_strncat(system_call, "*", MAX_FILENAME_LEN, MAX_FILENAME_LEN);
  877.       s_strncat(system_call, dictionary_ext, 
  878.                 MAX_FILENAME_LEN, MAX_FILENAME_LEN);
  879.       system(system_call);
  880.       s_free(system_call);
  881.       */
  882.     }
  883.   }
  884.   /* insert only new fields, old fields not deleted and
  885.    * adding new words in global dictionary
  886.    */
  887.   if(*create_new_fields && field_adding_to_existing_index) {
  888.     *create_new_fields = false;
  889.   }
  890.   /* insert only new fields, old fields not deleted and 
  891.    * not updates global fields.
  892.    */
  893.   else if(*create_new_fields && !field_adding_to_existing_index) {
  894.     db->doc_table_allocated_entries = 1;
  895.     s_free(field_name);
  896.   }
  897.   return(0);
  898. }
  899.  
  900. /* ------------------------------------------------------------- */
  901. /* open stream for each field.
  902.  * return 0, success.
  903.  * return 1, error
  904.  */
  905.  
  906. boolean open_field_streams_init(initialize, field_adding_to_existing_index, field_id, db)
  907.      boolean initialize;
  908.      boolean field_adding_to_existing_index;
  909.      long field_id;
  910.      database* db;
  911. {
  912.   char file[1001];
  913.   
  914.   if(db->field_index_streams == NULL)
  915.     db->field_index_streams = (FILE**)s_malloc((size_t)sizeof(FILE*));
  916.   if(db->field_dictionary_streams == NULL)
  917.     db->field_dictionary_streams = (FILE**)s_malloc((size_t)sizeof(FILE*));
  918.  
  919.   /* ext_open_database for fields */
  920.   if(initialize) {
  921.     *(db->field_index_streams) = NULL;
  922.     *(db->field_index_streams) = 
  923.       s_fopen(field_index_filename(file, db->fields[field_id].field_name, db), 
  924.               "w+b");
  925.     if(*(db->field_index_streams) == NULL) {
  926.       waislog(WLOG_HIGH, WLOG_ERROR,
  927.               "2can't open the inverted index file of field %s\n", 
  928.               db->fields[field_id].field_name);
  929.       disposeDatabase(db);
  930.       return(1);
  931.     }
  932.   }
  933.   else {
  934.     *(db->field_dictionary_streams) = 
  935.       s_fopen(field_dictionary_filename(file, 
  936.                                         db->fields[field_id].field_name, db), 
  937.               "r+b");
  938.     if (*(db->field_dictionary_streams) == NULL){ 
  939.       if(!field_adding_to_existing_index) {
  940.         waislog(WLOG_HIGH, WLOG_ERROR,
  941.                 "can't open the word hash file %s\n",file); 
  942.         disposeDatabase(db);
  943.         return(1);
  944.       }
  945.     }
  946.     *(db->field_index_streams) = 
  947.       s_fopen(field_index_filename(file, db->fields[field_id].field_name, db), 
  948.               "r+b");
  949.     if(*(db->field_index_streams) == NULL) {
  950.       if(field_adding_to_existing_index) {
  951.         *(db->field_index_streams) = 
  952.           s_fopen(field_index_filename(file,db->fields[field_id].field_name,db), 
  953.                   "w+b");
  954.         if(*(db->field_index_streams) == NULL) {
  955.           waislog(WLOG_HIGH, WLOG_ERROR,
  956.                   "2can't open the inverted index file of field %s\n", 
  957.                   db->fields[field_id].field_name);
  958.           disposeDatabase(db);
  959.           return(1);
  960.         }
  961.       }
  962.       else {
  963.         waislog(WLOG_HIGH, WLOG_ERROR,
  964.                 "2can't open the inverted index file of field %s\n", 
  965.                 db->fields[field_id].field_name);
  966.         disposeDatabase(db);
  967.         return(1);
  968.       }
  969.     }
  970.   }
  971.   return(0);
  972. }
  973.  
  974. boolean open_global_Database(initialize, db)
  975.      boolean initialize;
  976.      database* db;
  977. {
  978.   char file[MAX_FILE_NAME_LEN + 1 ];
  979.   
  980.   if(initialize == false) {
  981.     db->dictionary_stream = s_fopen(dictionary_filename(file, db), "r+b");
  982.     if (db->dictionary_stream == NULL) { 
  983.       waislog(WLOG_HIGH,WLOG_ERROR,"can't open the word hash file %s\n",file); 
  984.       disposeDatabase(db);
  985.       return(false);
  986.     }
  987.   }
  988.   return(ext_open_database(db, initialize, false));
  989. }
  990.